package com.yfs.cloud.util;

import java.util.Base64;
import java.util.Date;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yfs.cloud.commons.Constants;
import com.yfs.cloud.config.BusinessProperties;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
* @Company: 影法師工作室
* @Description: jwt 工具类, 因为只需要生成 jwt, 而不需要解析 jwt, 所以只有生成方法而没有解析方法, 网关中的 JWTUtil 正好相反
* @author 影法師  
* @date 2020年8月24日 下午11:13:21 
* @version V1.0
 */
@Component
public class JWTUtil {

	@Autowired
	private BusinessProperties businessProperties;

	/**
	* @Description: 生成加密后的秘钥 secretKey 
	* @author 影法師 
	* @date 2020年8月25日 上午12:08:41 
	* @version V1.0 
	* @param @return    
	* @return SecretKey    
	* @throws
	 */
	private SecretKey generalKey() {
		byte[] encodedKey = Base64.getDecoder().decode(businessProperties.getJwt().getSecret());
		SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
		return key;
	}

	/**
	* @Description: 获取jwt 
	* @author 影法師 
	* @date 2020年8月24日 下午11:59:07 
	* @version V1.0 
	* @param @param param 要塞入 jwt 中的东西
	* @param @return    
	* @return String    
	* @throws
	 */
	public String getJWT(Map<String, Object> param) {
		SecretKey secretKey = generalKey();
		// 该jwt授予谁
		return Jwts.builder()
				// payload中自定义属性, 因为 用户的权限、角色变动频繁, 所以这种信息一般不放进 jwt 中去, 而是直接去数据库查询, 或者丢到缓存中去
				.addClaims(param)
				// 颁发者
				.setIssuer(Constants.JWT_SUBJECT)
				// 该jwt是何时颁发的
				.setIssuedAt(new Date())
				// 设置过期时间, 一分钟之后过期, 线上环境一般 7 天后过期
				.setExpiration(new Date(System.currentTimeMillis() + businessProperties.getJwt().getExpire()))
				// 设置 signature, BASE64 只能指定是 HMAC式的签名, 不然报错 Base64-encoded key bytes may only
				// be specified for HMAC signatures. If using RSA or Elliptic Curve, use the
				// signWith(SignatureAlgorithm, Key) method instead.
				.signWith(SignatureAlgorithm.HS256, secretKey)
				// 上面会形成很长的一串, 这里让它紧凑一点, 所以压缩一下
				.compact();
	}

}